#ifndef webhttpd__Basic
#define webhttpd__Basic

#define PCRE2_STATIC
#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <glib.h>
#include <uv.h>
#include <pcre2.h>

#include <webhttpd/HttpRequest.h>
#include <webhttpd/HttpResponse.h>

extern uv_loop_t* loop;
extern uv_tcp_t server;
extern GHashTable* RouteMap;

static HttpResponse not_found_response(HttpRequest request);

static HttpResponse error_server_response(HttpRequest request);

static HttpResponse not_acceptable_response();

static void add_route(char* route_pattern, HttpResponse(*handler)(HttpRequest));

static void free_http_request(HttpRequest* request) {
    if (request == NULL) {
        return; // 如果请求为空，直接返回
    }

    // 释放 headers 中的每个键和值
    if (request->headers != NULL) {
        // 最后释放哈希表本身
        g_hash_table_destroy(request->headers);
    }

    // 释放 body.content 的内存
    if (request->body.content != NULL) {
        free(request->body.content);
    }

    // 最后释放 HttpRequest 结构体本身的内存
    free(request);
}

static void free_http_response(HttpResponse* response) {
    if (response == NULL) {
        return; // 如果响应为空，直接返回
    }

    // 释放 headers 中的每个键和值
    if (response->headers != NULL) {
        // 最后释放哈希表本身
        g_hash_table_destroy(response->headers);
    }

    // 释放 body.content 的内存
    if (response->body.content != NULL) {
        free(response->body.content);
    }

    // 最后释放 HttpResponse 结构体本身的内存
    //free(response);
}

static void free_http_response_raw(HttpResponseRaw* response_raw) {
    if (response_raw == NULL) {
        return; // 如果原始响应为空，直接返回
    }

    // 释放 content 的内存
    if (response_raw->content != NULL) {
        free(response_raw->content);
    }

    // 最后释放 HttpResponseRaw 结构体本身的内存
    free(response_raw);
}

static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
    // 分配内存用于接收数据
    *buf = uv_buf_init((char*)malloc(suggested_size), suggested_size);
}

static void on_write(uv_write_t* req, int status) {
    if (status) {
        fprintf(stderr, "Write failed: %s\n", uv_strerror(status));
    }


    free(req);
}

static void on_read(uv_stream_t* client, ssize_t nread, const uv_buf_t* buf) {
    if (nread < 0) {
        if (nread != UV_EOF) {
            fprintf(stderr, "Read error: %s\n", uv_strerror(nread));
        }
        uv_close((uv_handle_t*)client, NULL);
        return;
    }

    // 此处开始解析客户端请求

    struct sockaddr_in client_addr;
    int len = sizeof(client_addr);
    int client_port = 0; // 获取端口号
    char client_ip[INET_ADDRSTRLEN];


    if (uv_tcp_getpeername((uv_tcp_t*)client, (struct sockaddr*)&client_addr, &len) == 0) {
        uv_ip4_name(&client_addr, client_ip, sizeof(client_ip)); // 获取IP地址
        client_port = ntohs(client_addr.sin_port);
    }
    else {
        // fprintf(stderr, "Failed to get peer name\n");
    }

    // 解析
    HttpRequest* request = parse_request(buf->base, nread);
    HttpResponse(*handler)(HttpRequest) = NULL;
    HttpResponse response;

    if (request != NULL) {
        request->remote_port = client_port;
        strcpy(request->remote_addr, client_ip);

        // 遍历路由找到匹配

        // 获取所有的键
        GList* keys = g_hash_table_get_keys(RouteMap);

        // 使用 GList 循环遍历每个键
        GList* iter;

        for (iter = keys; iter != NULL; iter = iter->next) {
            char* route_pattern = iter->data;

            pcre2_code* re;
            pcre2_match_data* match_data;
            int errornumber;
            PCRE2_SIZE erroroffset;

            // 编译正则表达式
            re = pcre2_compile(
                (PCRE2_SPTR)route_pattern, // 正则表达式
                PCRE2_ZERO_TERMINATED, // 字符串以 NULL 结尾
                0, // 编译标志
                &errornumber, // 错误代码
                &erroroffset, // 错误位置
                NULL); // 未使用的工作区

            if (re == NULL) {
                printf("Regex compile failed at offset %d\n", (int)erroroffset);
                return;
            }

            // 创建匹配数据对象
            match_data = pcre2_match_data_create_from_pattern(re, NULL);

            // 执行匹配
            int rc = pcre2_match(
                re, // 正则表达式
                (PCRE2_SPTR)request->path, // 要匹配的字符串
                strlen(request->path), // 字符串的长度
                0, // 从字符串开始匹配
                0, // 匹配标志
                match_data, // 匹配数据
                NULL); // 未使用的工作区

            if (rc >= 0) {
                // 匹配成功
                handler = g_hash_table_lookup(RouteMap, route_pattern);
                pcre2_code_free(re);
                pcre2_match_data_free(match_data);
                break;
            }
            else {
                // 匹配失败
                handler = NULL;
            }

            // 释放内存
            pcre2_code_free(re);
            pcre2_match_data_free(match_data);
        }

        if (handler == NULL) {
            // 触发 404.
            handler = &not_found_response;
        }

        response = handler(*request);
        printf("%s -- %s %d\n", request->remote_addr, request->path, response.status_code);

        free_http_request(request);
    }
    else {
        // 解析失败
        response = not_acceptable_response();
        printf("%s -- %s %d\n", client_ip, "错误的协议内容", 406);
    }


    HttpResponseRaw* response_raw = parse_response(&response);

    uv_buf_t res_buf = uv_buf_init((char*)malloc(response_raw->size), response_raw->size);
    memcpy(res_buf.base, response_raw->content, response_raw->size);

    // 使用 uv_write 发送数据
    uv_write_t* write_req = (uv_write_t*)malloc(sizeof(uv_write_t));
    uv_write(write_req, client, &res_buf, 1, on_write);

    // 释放接收到的数据内存
    if (buf->base) {
        free(buf->base);
    }

    if (res_buf.base) {
        free(res_buf.base);
    }

    free_http_response_raw(response_raw);
    free_http_response(&response);
}

static void on_new_connection(uv_stream_t* server, int status) {
    if (status < 0) {
        fprintf(stderr, "新建链接错误: %s\n", uv_strerror(status));
        return;
    }

    uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));
    uv_tcp_init(loop, client);

    if (uv_accept(server, (uv_stream_t*)client) == 0) {
        uv_read_start((uv_stream_t*)client, on_alloc_buffer, on_read);
    }
    else {
        uv_close((uv_handle_t*)client, NULL);
    }

}

static inline void init_server() {
    RouteMap = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
}

/**
 * @brief 运行服务器
 *
 * @param addr 服务器地址
 * @param port 端口号
 *
 * @return 状态码
 */
static inline int run_server(const char* addr, const int port) {
    loop = uv_default_loop();

    uv_tcp_init(loop, &server);

    struct sockaddr_in sockaddr;
    int len = sizeof(sockaddr);

    uv_ip4_addr(addr, port, &sockaddr);

    uv_tcp_bind(&server, (const struct sockaddr*)&sockaddr, 0);

    int listen_status = uv_listen((uv_stream_t*)&server, SOMAXCONN, on_new_connection);

    if (listen_status == UV_EADDRINUSE) {
        printf("不能成功绑定套接字，原因: %s\n", uv_strerror(listen_status));
        return -1;
    }

    uv_tcp_getsockname(&server, (struct sockaddr*)&sockaddr, &len);

    printf("Server listening on %d ...\n", ntohs(sockaddr.sin_port));
    printf(" * http://%s:%d\n", addr, ntohs(sockaddr.sin_port));

    return uv_run(loop, UV_RUN_DEFAULT);
}

#endif


static void add_route(char* route_pattern, HttpResponse(*handler)(HttpRequest)) {
    g_hash_table_insert(RouteMap, g_strdup(route_pattern), (gpointer)handler);
}


static HttpResponse not_found_response(HttpRequest request) {
    HttpResponse response;
    response.status_code = 404;
    response.headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

    g_hash_table_insert(response.headers, g_strdup("Content-Type"), g_strdup("text/html; charset=utf-8"));

    response.body.content = malloc(100);
    response.body.size = strlen("404 Not Found") + 1;
    strcpy(response.body.content, "404 Not Found");
    return response;
}

static HttpResponse error_server_response(HttpRequest request) {
    HttpResponse response;
    response.status_code = 500;
    response.headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

    g_hash_table_insert(response.headers, g_strdup("Content-Type"), g_strdup("text/html; charset=utf-8"));

    response.body.content = malloc(500);
    response.body.size = strlen("500 Server Error") + 1;
    strcpy(response.body.content, "500 Server Error");
    return response;
}

static HttpResponse not_acceptable_response() {
    HttpResponse response;
    response.status_code = 406;
    response.headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

    g_hash_table_insert(response.headers, g_strdup("Content-Type"), g_strdup("text/html; charset=utf-8"));

    response.body.content = malloc(406);
    response.body.size = strlen("Not Acceptable") + 1;
    strcpy(response.body.content, "Not Acceptable");
    return response;
}
